package com.uzai.console.service.fd.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.JsApiBaseDTO;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.dto.fadan.CardContent;
import com.uzai.common.dto.fadan.FollowMsgDto;
import com.uzai.common.dto.fadan.FollowQfMsgDto;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.console.common.utils.DateUtil;
import com.uzai.console.common.utils.Tools;
import com.uzai.console.dto.fd.fdfollowconfig.FdFollowConfigQuery;
import com.uzai.console.dto.fd.fdfollowedmsg.FdFollowedMsgQuery;
import com.uzai.console.entity.FdFollowConfig;
import com.uzai.console.entity.FdFollowConfigQf;
import com.uzai.console.entity.FdFollowGroup;
import com.uzai.console.entity.FdFollowedMsg;
import com.uzai.console.mapper.FdFollowConfigMapper;
import com.uzai.console.mapper.FdFollowConfigQfMapper;
import com.uzai.console.mapper.FdFollowedMsgMapper;
import com.uzai.console.service.fd.FdFollowSendService;
import com.uzai.console.service.fd.FdFollowSendSyncService;
import com.uzai.console.service.ratelimit.RatelimitService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 发单跟发配置
 * @author liuqi
 * @date 2021年08月13日 11:34
 */
@Service
public class FdFollowSendSyncServiceImpl implements FdFollowSendSyncService {

    Logger logger = LoggerFactory.getLogger(FdFollowSendSyncServiceImpl.class);

    @Autowired
    private FdFollowConfigMapper fdFollowConfigMapper;
    @Autowired
    private RatelimitService ratelimitService;
    @Autowired
    private FdFollowSendService fdFollowSendService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private FdFollowConfigQfMapper fdFollowConfigQfMapper;
    @Autowired
    private FdFollowedMsgMapper fdFollowedMsgMapper;

    /**
     * 跟发发单发送
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param
     * @return null
     */
    @Async("taskExecutor")
    public void followSendSync(FollowMsgDto followMsgDto){

        logger.info("-----调用发单跟发功能--发送发单任务--xxlJob start--followMsgDto={}", JSONObject.toJSONString(followMsgDto));

        //限流判断-同一个发单同一个机器人1分钟只能调用一次
        String key = followMsgDto.getServerMsgId() + "_" + followMsgDto.getDeviceUniqueId();
        boolean inRateLimit = ratelimitService.inRateLimit("fdFollowSend-key=" + key,1,30);
        if (!inRateLimit){
            //logger.info("--inRateLimit false. tradeno={}",alipayDetail.getTradeno());
            return;
        }

        //查询当前所有开启的自动发圈的配置方案
        int now = DateUtil.getNowTime();
        String yyyyMMdd = Tools.getDateFormat(new Date(), "yyyy-MM-dd");
        // 获取当前时间
        LocalDateTime now_localDateTime = LocalDateTime.now();

        FdFollowConfigQuery fdFollowConfigQuery = new FdFollowConfigQuery();
        fdFollowConfigQuery.setMerId(followMsgDto.getMerId());
        fdFollowConfigQuery.setStatus(1); //启动
        fdFollowConfigQuery.setDeviceUniqueId(followMsgDto.getDeviceUniqueId());
        fdFollowConfigQuery.setGroupWxid(followMsgDto.getGroupWxid());
        fdFollowConfigQuery.setGroupUserWxid(followMsgDto.getSendWxid());
        //查询所有的跟发配置记录
        Page<FdFollowConfig> page = new Page<>();
        page.setCurrent(1);//只查第一页
        page.setSize(10); //每页查询10个
        page.addOrder(OrderItem.asc("id"));//默认id升序
        Long idStart = 0L;
        List<FdFollowConfig> fdFollowConfigList = fdFollowConfigMapper.findByList(page, fdFollowConfigQuery);
        while (fdFollowConfigList != null && fdFollowConfigList.size() > 0){
            for (FdFollowConfig fdFollowConfig : fdFollowConfigList){
                try{
                    if(fdFollowConfig.getId().longValue() > idStart.longValue()){
                        idStart = fdFollowConfig.getId();
                    }

                    //开始限制时间（HH:mm）
                    String limitTimeStart = fdFollowConfig.getLimitTimeStart();
                    if(StringUtils.isBlank(limitTimeStart)){
                        limitTimeStart = "00:00";
                    }

                    //结束限制时间（HH:mm）
                    String limitTimeEnd = fdFollowConfig.getLimitTimeEnd();
                    if(StringUtils.isBlank(limitTimeEnd)){
                        limitTimeEnd = "23:59";
                    }

                    //判断当前时间是否在自动任务开启时间区间内
                    boolean withinTimeInterval = Tools.isWithinTimeInterval(now_localDateTime, LocalTime.parse(limitTimeStart), LocalTime.parse(limitTimeEnd));
                    //不在区间内，则跳过
                    if(!withinTimeInterval){
                        continue;
                    }

                    //自动发送发单
                    fdFollowSendService.followSendFd(followMsgDto, fdFollowConfig);
                }catch (Exception e){

                }
            }
            fdFollowConfigQuery.setIdStart(idStart);
            fdFollowConfigList = fdFollowConfigMapper.findByList(page, fdFollowConfigQuery);
        }
        //删除限流
        redisTemplate.delete(key);
    }

    /**
     * 气氛组跟发发单发送内容
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param
     * @return null
     */
    @Async("taskExecutor")
    public void followQfSendSync(FollowQfMsgDto followQfMsgDto){
        logger.info("-----气氛组调用发单跟发功能---xxlJob start--followQfMsgDto={}", JSONObject.toJSONString(followQfMsgDto));

        //限流判断-同一个发单同一个机器人30秒只能调用一次
        String key = followQfMsgDto.getMsgId() + "_" + followQfMsgDto.getDeviceUniqueId();
        boolean inRateLimit = ratelimitService.inRateLimit("followQfSendSync-key=" + key,1,30);
        if (!inRateLimit){
            //logger.info("--inRateLimit false. tradeno={}",alipayDetail.getTradeno());
            return;
        }

        //查询当前自动跟发任务
        FdFollowConfigQf fdFollowConfigQf = fdFollowConfigQfMapper.selectById(followQfMsgDto.getFdFollowConfigQfId(), followQfMsgDto.getMerId());

        if(fdFollowConfigQf != null){
                //自动发送发单
            fdFollowSendService.followQfSendFd(followQfMsgDto, fdFollowConfigQf);
        }

        //删除限流
        redisTemplate.delete(key);
    }


    /**
     * 保存跟发发单发送内容
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param
     * @return null
     */
    public void saveFollowSendMsg(FollowMsgDto followMsgDto){

        //限流判断-同一个发单同一个机器人1分钟只能调用一次
        String key = followMsgDto.getServerMsgId() + "_" + followMsgDto.getDeviceUniqueId();
        boolean inRateLimit = ratelimitService.inRateLimit("saveFollowSendMsg-key=" + key,1,30);
        if (!inRateLimit){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "30秒内同一个机器人只能处理同一条消息；key=" + key);
        }

        //查询该消息是否已经存在
        FdFollowedMsg fdFollowedMsgOld = fdFollowedMsgMapper.selectByDeviceUniqueIdAndServerMsgId(followMsgDto.getDeviceUniqueId(), followMsgDto.getServerMsgId());
        if(fdFollowedMsgOld != null){
            throw  new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "该消息已经存在");
        }

        int now = DateUtil.getNowTime();
        FdFollowedMsg fdFollowedMsg = new FdFollowedMsg();
        BeanUtils.copyProperties(followMsgDto, fdFollowedMsg);
        fdFollowedMsg.setId(IdWorker.getId());
        fdFollowedMsg.setMerId(followMsgDto.getMerId());
        fdFollowedMsg.setDeviceUniqueId(followMsgDto.getDeviceUniqueId());
        fdFollowedMsg.setDeviceId(followMsgDto.getDeviceId());
        fdFollowedMsg.setDeviceType(followMsgDto.getDeviceType());
        fdFollowedMsg.setMsgId(followMsgDto.getMsgId());
        fdFollowedMsg.setServerMsgId(followMsgDto.getServerMsgId());
        fdFollowedMsg.setLocalMsgId(followMsgDto.getLocalMsgId());
        fdFollowedMsg.setSendWxid(followMsgDto.getSendWxid());
        fdFollowedMsg.setSendNick(followMsgDto.getSendNick());
        fdFollowedMsg.setSendtime(Tools.getLong(followMsgDto.getSendtime()));
        fdFollowedMsg.setGroupWxid(followMsgDto.getGroupWxid());
        fdFollowedMsg.setGroupName(followMsgDto.getGroupName());
        fdFollowedMsg.setMsgType(followMsgDto.getMsgType());
        fdFollowedMsg.setContent(followMsgDto.getContent());
        fdFollowedMsg.setCard(JSONObject.toJSONString(followMsgDto.getCard()));
        fdFollowedMsg.setStatus(0);//未处理
        fdFollowedMsg.setCreateTime(now);
        fdFollowedMsg.setUpdateTime(now);
        fdFollowedMsgMapper.insertSelective(fdFollowedMsg);
    }

    /**
     * 发送跟发发单发送内容
     * @author liuqi
     * @date 2021/8/13 11:38
     * @param
     * @return null
     */
    @Async("taskExecutor")
    public void sendFollowSendMsg(){
        //限流key
        String taskLimitKet = "sendFollowSendMsg-key-";
        Object object = redisTemplate.opsForValue().get(taskLimitKet);
        if(object != null){
            return;
        }
        //保存限流key
        redisTemplate.opsForValue().set(taskLimitKet, taskLimitKet, 10, TimeUnit.MINUTES);

        int now = DateUtil.getNowTime();
        // 获取当前时间
        LocalDateTime now_localDateTime = LocalDateTime.now();

        //按照发送时间排序查询10条发单消息
        FdFollowedMsgQuery fdFollowedMsgQuery = new FdFollowedMsgQuery();
        fdFollowedMsgQuery.setStatus(0); //查询未处理
        fdFollowedMsgQuery.setQueryEndTime(now - 1*60); //查询1分钟之前的消息

        //查询所有的跟发配置记录
        Page<FdFollowedMsg> page = new Page<>();
        page.setCurrent(1);//只查第一页
        page.setSize(10); //每页查询10个
        page.addOrder(OrderItem.asc("sendtime"), OrderItem.asc("id"));//默认发送时间和id升序
        List<FdFollowedMsg> fdFollowedMsgList = fdFollowedMsgMapper.findByListDistinctDviceAndGroupAndUser(page, fdFollowedMsgQuery);
        while (fdFollowedMsgList != null && fdFollowedMsgList.size() > 0){
            for (FdFollowedMsg fdFollowedMsg : fdFollowedMsgList){
                try{
                    //限流判断-同一个机器人同一个群监控同一个会员 5秒处理一次消息
                    String keyLimit = fdFollowedMsg.getDeviceUniqueId() + "_" + fdFollowedMsg.getGroupWxid() + fdFollowedMsg.getSendWxid();
                    boolean inRateLimit = ratelimitService.inRateLimit("followQfSendSync-deviceGroupUserWxid-keyLimit=" + keyLimit,1,5);
                    if (!inRateLimit){
                        //logger.info("--inRateLimit false. tradeno={}",alipayDetail.getTradeno());
                        continue;
                    }
                    logger.info("--自动处理跟发消息-fdFollowedMsg={}", JSONObject.toJSONString(fdFollowedMsg));
                    //查询出来就修改成已处理
                    fdFollowedMsg.setStatus(1);
                    fdFollowedMsg.setFollowTime(DateUtil.getNowTime());
                    fdFollowedMsg.setUpdateTime(DateUtil.getNowTime());
                    fdFollowedMsgMapper.updateStatus(fdFollowedMsg);

                    //删除配置方案是否存在，不存在，则不跟发
                    FdFollowConfig fdFollowConfig = fdFollowConfigMapper.selectByDeviceUniqueIdAndGroupWxidAndGroupUserWxid(fdFollowedMsg.getDeviceUniqueId(), fdFollowedMsg.getGroupWxid(), fdFollowedMsg.getSendWxid());
                    if(fdFollowConfig == null){
                        continue;
                    }

                    //开始限制时间（HH:mm）
                    String limitTimeStart = fdFollowConfig.getLimitTimeStart();
                    if(StringUtils.isBlank(limitTimeStart)){
                        limitTimeStart = "00:00";
                    }

                    //结束限制时间（HH:mm）
                    String limitTimeEnd = fdFollowConfig.getLimitTimeEnd();
                    if(StringUtils.isBlank(limitTimeEnd)){
                        limitTimeEnd = "23:59";
                    }

                    //判断当前时间是否在自动任务开启时间区间内
                    boolean withinTimeInterval = Tools.isWithinTimeInterval(now_localDateTime, LocalTime.parse(limitTimeStart), LocalTime.parse(limitTimeEnd));
                    //不在区间内，则跳过
                    if(!withinTimeInterval){
                        continue;
                    }

                    //自动发送发单
                    FollowMsgDto followMsgDto = new FollowMsgDto();
                    BeanUtils.copyProperties(fdFollowedMsg, followMsgDto);
                    followMsgDto.setMsgId(fdFollowedMsg.getMsgId());
                    followMsgDto.setServerMsgId(fdFollowedMsg.getServerMsgId());
                    followMsgDto.setLocalMsgId(fdFollowedMsg.getLocalMsgId());
                    followMsgDto.setSendWxid(fdFollowedMsg.getSendWxid());
                    followMsgDto.setSendNick(fdFollowedMsg.getSendNick());
                    followMsgDto.setGroupWxid(fdFollowedMsg.getGroupWxid());
                    followMsgDto.setGroupName(fdFollowedMsg.getGroupName());
                    followMsgDto.setMsgType(fdFollowedMsg.getMsgType());
                    followMsgDto.setContent(fdFollowedMsg.getContent());
                    followMsgDto.setSendtime(fdFollowedMsg.getSendtime());
                    followMsgDto.setMerId(fdFollowedMsg.getMerId());
                    followMsgDto.setDeviceId(fdFollowedMsg.getDeviceId());
                    followMsgDto.setDeviceUniqueId(fdFollowedMsg.getDeviceUniqueId());
                    followMsgDto.setDeviceType(fdFollowedMsg.getDeviceType());
                    try {
                        followMsgDto.setCard(JSONObject.parseObject(fdFollowedMsg.getCard(), CardContent.class));
                    }catch (Exception e){
                    }

                    fdFollowSendService.followSendFd(followMsgDto, fdFollowConfig);

                }catch (Exception e){

                }
            }
            fdFollowedMsgList = fdFollowedMsgMapper.findByListDistinctDviceAndGroupAndUser(page, fdFollowedMsgQuery);
        }

        //删除限流key
        redisTemplate.delete(taskLimitKet);

    }


    /**
     * 异步删除4小时之前的跟发消息记录
     * @author jitwxs
     * @date 2022/1/16 17:16
     */
    @Async("taskExecutor")
    public void deleteFdFollowedMsgSync(){
        int deleteDay = DateUtil.getNowTime() - 4*60*60;
        fdFollowedMsgMapper.deleteBeforeDay(deleteDay);
    }

}
